const ora = require('ora');
const chalk = require('chalk');

/**
 * 进度显示工具
 * @class Progress
 */
class Progress {
  constructor() {
    this.spinners = new Map();
    this.currentSpinner = null;
  }

  /**
   * 创建一个新的进度指示器
   * @param {string} text - 显示文本
   * @param {Object} options - 选项
   * @returns {Object} spinner 实例
   */
  create(text, options = {}) {
    const spinner = ora({
      text,
      color: options.color || 'cyan',
      hideCursor: options.hideCursor !== false
    }).start();

    const id = Date.now().toString() + Math.random().toString(36);
    this.spinners.set(id, spinner);

    return { id, spinner };
  }

  /**
   * 更新进度文本
   * @param {Object} spinnerInfo - spinner 信息
   * @param {string} text - 新文本
   */
  updateText(spinnerInfo, text) {
    if (spinnerInfo && spinnerInfo.spinner) {
      spinnerInfo.spinner.text = text;
    }
  }

  /**
   * 成功完成
   * @param {Object} spinnerInfo - spinner 信息
   * @param {string} text - 完成文本
   */
  succeed(spinnerInfo, text) {
    if (spinnerInfo && spinnerInfo.spinner) {
      spinnerInfo.spinner.succeed(text);
      this.spinners.delete(spinnerInfo.id);
    }
  }

  /**
   * 失败完成
   * @param {Object} spinnerInfo - spinner 信息
   * @param {string} text - 失败文本
   */
  fail(spinnerInfo, text) {
    if (spinnerInfo && spinnerInfo.spinner) {
      spinnerInfo.spinner.fail(text);
      this.spinners.delete(spinnerInfo.id);
    }
  }

  /**
   * 警告完成
   * @param {Object} spinnerInfo - spinner 信息
   * @param {string} text - 警告文本
   */
  warn(spinnerInfo, text) {
    if (spinnerInfo && spinnerInfo.spinner) {
      spinnerInfo.spinner.warn(text);
      this.spinners.delete(spinnerInfo.id);
    }
  }

  /**
   * 停止并移除 spinner
   * @param {Object} spinnerInfo - spinner 信息
   */
  stop(spinnerInfo) {
    if (spinnerInfo && spinnerInfo.spinner) {
      spinnerInfo.spinner.stop();
      this.spinners.delete(spinnerInfo.id);
    }
  }

  /**
   * 停止所有 spinner
   */
  stopAll() {
    for (const [id, spinner] of this.spinners) {
      spinner.stop();
    }
    this.spinners.clear();
  }

  /**
   * 创建文件分析进度器
   * @param {number} total - 总文件数
   * @param {Object} options - 选项
   * @returns {Object} 文件分析进度器
   */
  createFileAnalyzer(total, options = {}) {
    let processed = 0;
    let errors = 0;
    const startTime = Date.now();

    const spinnerInfo = this.create(`分析文件 0/${total}`, {
      color: options.color || 'blue'
    });

    return {
      update: (fileName, success = true) => {
        processed++;
        if (!success) errors++;

        const percentage = Math.round((processed / total) * 100);
        const elapsed = Date.now() - startTime;
        const remaining = processed > 0 ? Math.round(elapsed * (total - processed) / processed) : 0;
        const remainingText = remaining > 0 ? this.formatTime(remaining) : '即将完成';

        this.updateText(spinnerInfo,
          `分析文件 ${processed}/${total} (${percentage}%) - ${errors} 错误 - 预计剩余: ${remainingText}`
        );
      },

      succeed: (message) => {
        const duration = this.formatTime(Date.now() - startTime);
        this.succeed(spinnerInfo,
          message || `分析完成！处理 ${processed} 个文件，耗时 ${duration}`
        );
      },

      fail: (error) => {
        this.fail(spinnerInfo, `分析失败: ${error.message}`);
      }
    };
  }

  /**
   * 创建目录扫描进度器
   * @param {string} directory - 目录路径
   * @returns {Object} 目录扫描进度器
   */
  createDirectoryScanner(directory) {
    const spinnerInfo = this.create(`扫描目录: ${directory}`, {
      color: 'magenta'
    });

    return {
      scanning: (currentDir) => {
        this.updateText(spinnerInfo, `正在扫描: ${currentDir}`);
      },

      found: (count) => {
        this.updateText(spinnerInfo, `找到 ${count} 个 Vue 文件`);
      },

      succeed: (count) => {
        this.succeed(spinnerInfo, `扫描完成，找到 ${count} 个 Vue 文件`);
      },

      fail: (error) => {
        this.fail(spinnerInfo, `扫描失败: ${error.message}`);
      }
    };
  }

  /**
   * 创建报告生成进度器
   * @returns {Object} 报告生成进度器
   */
  createReportGenerator() {
    const spinnerInfo = this.create('正在生成分析报告...', {
      color: 'green'
    });

    return {
      generating: () => {
        this.updateText(spinnerInfo, '正在分析数据并生成报告...');
      },

      saving: (filename) => {
        this.updateText(spinnerInfo, `正在保存报告到: ${filename}`);
      },

      succeed: (filename) => {
        this.succeed(spinnerInfo, `报告已保存: ${filename}`);
      },

      fail: (error) => {
        this.fail(spinnerInfo, `生成报告失败: ${error.message}`);
      }
    };
  }

  /**
   * 显示简单的进度条
   * @param {number} current - 当前进度
   * @param {number} total - 总数
   * @param {number} width - 进度条宽度
   * @param {string} label - 标签
   */
  showProgressBar(current, total, width = 40, label = 'Progress') {
    const percentage = Math.round((current / total) * 100);
    const filled = Math.round((current / total) * width);
    const empty = width - filled;

    const bar = chalk.green('█'.repeat(filled)) + chalk.gray('█'.repeat(empty));
    const text = `${label}: ${bar} ${percentage}% (${current}/${total})`;

    // 清除当前行并显示新的进度条
    process.stdout.write('\r' + text);

    // 如果完成了，换行
    if (current === total) {
      process.stdout.write('\n');
    }
  }

  /**
   * 显示统计信息
   * @param {Object} stats - 统计信息
   */
  showStats(stats) {
    console.log(chalk.blue('\n📊 分析统计:'));
    console.log(`   文件总数: ${chalk.yellow(stats.totalFiles)}`);
    console.log(`   代码行数: ${chalk.yellow(stats.totalLines)}`);
    console.log(`   模板代码: ${chalk.cyan(stats.templateLines)} 行`);
    console.log(`   脚本代码: ${chalk.magenta(stats.scriptLines)} 行`);
    console.log(`   样式代码: ${chalk.green(stats.styleLines)} 行`);

    if (stats.errors.length > 0) {
      console.log(`   错误数量: ${chalk.red(stats.errors.length)}`);
    }
  }

  /**
   * 格式化时间
   * @param {number} milliseconds - 毫秒数
   * @returns {string} 格式化后的时间
   */
  formatTime(milliseconds) {
    const seconds = Math.floor(milliseconds / 1000);
    const minutes = Math.floor(seconds / 60);
    const hours = Math.floor(minutes / 60);

    if (hours > 0) {
      return `${hours}小时${minutes % 60}分钟`;
    } else if (minutes > 0) {
      return `${minutes}分钟${seconds % 60}秒`;
    } else {
      return `${seconds}秒`;
    }
  }

  /**
   * 清理所有资源
   */
  cleanup() {
    this.stopAll();
    process.stdout.clearLine();
    process.stdout.cursorTo(0);
  }
}

module.exports = Progress;